
#ifndef __UM_SP_COUNTED_BASE_WIN32_H
#define __UM_SP_COUNTED_BASE_WIN32_H


class sp_counted_base {

public:
	sp_counted_base() : m_use_count(1), m_weak_count(1) {
	}
	
	virtual ~sp_counted_base() {
	}

	virtual void dispose() = 0;

	virtual void destroy() {
		delete this;
	}

	void add_ref_copy() {
		InterlockedIncrement(&m_use_count);
	}

	bool add_ref_lock() {
		long tmp = static_cast<long const volatile&>(m_use_count);
		if (tmp == 0) {
			return false;
		}
		for (;;) {
			if (InterlockedCompareExchange(&m_use_count, tmp + 1, tmp) == tmp) {
				return true;		
			}
		}
	}

	void release() {
		if (InterlockedDecrement(&m_use_count) == 0) {
			dispose();
			weak_release();
		}
	}

	long use_count() const {
		return static_cast<long const volatile&>(m_use_count);
	}

	void weak_add_ref() {
		InterlockedIncrement(&m_weak_count);
	}

	void weak_release() {
		if (InterlockedDecrement(&m_weak_count) == 0) {
			destroy();
		}
	}

private:
	sp_counted_base(const sp_counted_base&);
	sp_counted_base& operator=(const sp_counted_base&);
	long m_use_count;
	long m_weak_count;
};


#endif // __UM_SP_COUNTED_BASE_WIN32_H